"""
Pydantic 数据模型

定义 API 请求和响应的数据结构
"""

from pydantic import BaseModel, EmailStr, Field, field_validator
from typing import Optional
from datetime import datetime
import re


# ========== 辅助函数 ==========

def validate_password_strength(password: str) -> bool:
    """
    验证密码强度
    
    要求：
    - 至少 8 个字符
    - 至少 1 个大写字母
    - 至少 1 个小写字母
    - 至少 1 个数字
    """
    if len(password) < 8:
        return False
    if not re.search(r"[A-Z]", password):
        return False
    if not re.search(r"[a-z]", password):
        return False
    if not re.search(r"\d", password):
        return False
    return True


# ========== Token 相关模型 ==========

class Token(BaseModel):
    """
    Token 响应模型
    
    登录成功后返回的 Token 信息
    """
    access_token: str = Field(..., description="访问令牌")
    refresh_token: str = Field(..., description="刷新令牌")
    token_type: str = Field(default="bearer", description="Token 类型")


class TokenPayload(BaseModel):
    """
    Token Payload 模型
    
    JWT Token 中的数据
    """
    sub: Optional[str] = None  # Subject (用户名)
    exp: Optional[int] = None  # Expiration Time
    iat: Optional[int] = None  # Issued At


# ========== 用户相关模型 ==========

class UserBase(BaseModel):
    """
    用户基础模型
    
    包含用户的基本信息
    """
    username: str = Field(..., min_length=3, max_length=50, description="用户名")
    email: EmailStr = Field(..., description="邮箱")
    full_name: Optional[str] = Field(None, max_length=100, description="全名")


class UserCreate(UserBase):
    """
    用户创建模型
    
    注册时使用
    """
    password: str = Field(..., min_length=8, max_length=100, description="密码")
    
    @field_validator("password")
    @classmethod
    def validate_password(cls, v):
        """验证密码强度"""
        if not validate_password_strength(v):
            raise ValueError(
                "Password must be at least 8 characters long and contain "
                "uppercase, lowercase, and digit"
            )
        return v


class UserUpdate(BaseModel):
    """
    用户更新模型
    
    更新用户信息时使用
    """
    email: Optional[EmailStr] = None
    full_name: Optional[str] = Field(None, max_length=100)
    

class UserResponse(UserBase):
    """
    用户响应模型
    
    返回给客户端的用户信息（不包含密码）
    """
    id: int
    is_active: bool
    is_superuser: bool
    created_at: datetime
    updated_at: datetime
    
    class Config:
        from_attributes = True  # 允许从 ORM 模型创建


class UserInDB(UserResponse):
    """
    数据库中的用户模型
    
    包含加密后的密码（仅内部使用）
    """
    hashed_password: str


# ========== 密码相关模型 ==========

class PasswordChange(BaseModel):
    """
    修改密码模型
    """
    old_password: str = Field(..., description="旧密码")
    new_password: str = Field(..., min_length=8, max_length=100, description="新密码")
    
    @field_validator("new_password")
    @classmethod
    def validate_password(cls, v):
        """验证新密码强度"""
        if not validate_password_strength(v):
            raise ValueError(
                "Password must be at least 8 characters long and contain "
                "uppercase, lowercase, and digit"
            )
        return v


# ========== 通用响应模型 ==========

class MessageResponse(BaseModel):
    """
    通用消息响应模型
    """
    message: str = Field(..., description="响应消息")


